package com.dnndo.common.utils.oss;


import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSException;
import com.dnndo.common.exception.CustomExceptions;
import com.dnndo.common.utils.DateUtils;
import com.dnndo.common.utils.StringUtils;
import com.dnndo.common.utils.uuid.Seq;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.io.IOUtils;
import org.apache.tika.Tika;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

@Data
@AllArgsConstructor
//固定代码，CV直接使用
@Log4j2
public class AliOssUtil {

    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;
    private String cdnUrl;
    //上传路径
    private String uploadPath;
    //协议路径
    private String protocolPath;
    //头像路径
    private String avatarPath;
    //形象照路径
    private String imagePhotoPath;

    /**
     * 网络路径上传文件
     * @param fileUrl 文件网络路径
     * @param path 表示在oss中存储的文件路径
     * return : 返回cdn访问路径
     */
    public String upload(String fileUrl,String path) {
        // 从网络下载图片
        InputStream inputStream;
        try {
            URL url = new URL(fileUrl);
            inputStream = url.openStream();
        } catch (Exception e) {
            log.info("图片下载失败");
            return null;
        }
        // 将InputStream转换为可重复读取的流
        // 因为InputStream不支持重复读(getFileExtension方法会读取一次，上传文件时再读取就读不到，上传的文件就不完整)
        byte[] bytes = null;
        try {
            bytes = IOUtils.toByteArray(inputStream);
        } catch (IOException e) {
            log.info("图片下载失败.......");
            return null;
        }
        InputStream stream1 = new ByteArrayInputStream(bytes);
        InputStream stream2 = new ByteArrayInputStream(bytes);

        //获取文件名
        String fileName = StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
                "", Seq.getId(Seq.uploadSeqType), getFileExtension(stream1));
        //在oss中存储名字
        String objectName = path + fileName;
        return this.upload(stream2, objectName);
    }


    /**
     * 文件上传
     *
     * @param bytes ：传入的文件要转为byte[]
     * @param objectName ：表示在oss中存储的文件名字。
     * @return ：返回cdn访问路径
     */
    public String upload(byte[] bytes, String objectName) {

        try {
            // 创建PutObject请求。
            OssClientHolder.getInstance().putObject(bucketName, objectName, new ByteArrayInputStream(bytes));
        } catch (OSSException | ClientException e) {
            log.error("上传失败{}", e.getMessage());
            return null;
        }
        //返回cdn访问路径
        return cdnUrl +
                "/" +
                objectName;
    }
    /**
     * 文件流上传文件
     * @param inputStream ：传入的文件流
     * @param objectName ：表示在oss中存储的文件名字。
     * @return ：返回cdn访问路径
     */
    private String upload(InputStream inputStream, String objectName) {
        try {
            // 创建PutObject请求。
            OssClientHolder.getInstance().putObject(bucketName, objectName, inputStream);
        } catch (OSSException | ClientException oe) {
            log.error("上传失败{}", oe.getMessage());
            return null;
        }
        //返回cdn访问路径
        return cdnUrl +
                "/" +
                objectName;
    }

    // 获取文件扩展名
    private String getFileExtension(InputStream inputStream) {
        // 检测文件类型
        Tika tika = new Tika();
        String mimeType = null;
        try {
            mimeType = tika.detect(inputStream);
        } catch (IOException e) {
            throw new CustomExceptions("获取文件扩展名失败");
        }
        return mimeType.split("/")[1];
    }
}
